home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / src / xad_Wrapster.lha / Wrapster.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-18  |  8.9 KB  |  282 lines

  1. /* Wrapster file archiver client for XAD.
  2.  * Copyright (C) 2000-2002 Stuart Caie <kyzer@4u.net>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  * 
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. /* Wrapster is a way of using the Napster MP3 sharing system to not only
  20.  * share MP3s, but any files you like.
  21.  * See http://www.unwrapper.com/ for more information, or do a Google
  22.  * search on "Wrapster".
  23.  *
  24.  * The CRC32 feature of Wrapster is ignored completely, for two reasons:
  25.  * - the Wrapster authors haven't told anybody what the CRC calculation is
  26.  * - because of this, other wrapper authors have used different CRCs!!!!
  27.  * Therefore, there's no real point checking.
  28.  */
  29.  
  30. /* From the Wrapster 2.0 .HLP file:
  31.  * Wrapster File Format for v1.0 and v2.0
  32.  *
  33.  * Ok... here is the official specification for the layout of a Wrapster
  34.  * file. This section is intended for programmers and anyone who might be
  35.  * curious about how this whole thing works. The reasons for including this
  36.  * specification is to encourage other programmers to write their own
  37.  * Wrapster clones for other Operating Systems, or to extend the features
  38.  * of the Windows version of Wrapster itself. If you extend the features of
  39.  * Wrapster, use some of the unused bytes so that your client can easily
  40.  * identify those files which it creates.
  41.  * 
  42.  * A Wrapster file will have the following format on disk:
  43.  * 
  44.  * Header
  45.  *   FrameHeader           4 bytes         0xFF, 0xFB, 0x18, 0x0C
  46.  *   Reserved (Unused)     6 bytes
  47.  *   Signature             10 bytes        "wrapster"#0#0
  48.  *   Version               8 bytes         "2.0"#0#0#0#0#0
  49.  *   FileCount             4 bytes
  50.  * 
  51.  * Wrapster File Entry
  52.  * 
  53.  * Immediately following the header of the file you will find FileCount
  54.  * entries each containing the following data
  55.  * 
  56.  *   OriginalFileName      256 bytes
  57.  *   Reserved (Unused)     32 bytes
  58.  *   CRC32                 4 bytes
  59.  *   Size                  4 bytes
  60.  *   FileData              Size bytes
  61.  * 
  62.  * Padding
  63.  * 
  64.  * After all file entries in the Wrapster file you will encounter padding
  65.  * that helps to assure that the files contained within the archive remain
  66.  * intact. This was done as a precaution since many downloads across
  67.  * Napster tend to get the last few bytes cut off.
  68.  * 
  69.  * ID3 Tag
  70.  * The last 128 bytes of the padding contain an MP3 identification tag that
  71.  * will show up in the play-list of programs like Winamp as an ID3 tag. You
  72.  * may put any values in here that you like. See the MP3 specification for
  73.  * more information.
  74.  */
  75.  
  76. /* Wrapster v3.0 format - reverse engineered
  77.  *
  78.  * Format is entirely encapsulated in MP3 frames:
  79.  * 0xFF,0xFB,0x90,0x04,{413 bytes of actual data}
  80.  *
  81.  * Header
  82.  *   Reserved (Unused)     6 bytes
  83.  *   Signature             10 bytes        "wwapster"#0#0
  84.  *   Version               8 bytes         "3.0"#0#0#0#0#0
  85.  *   FileCount             4 bytes
  86.  *
  87.  * Then follows [FileCount] file headers:
  88.  *
  89.  * File Header
  90.  *   OriginalFileName      256 bytes
  91.  *   Reserved (Unused)     32 bytes
  92.  *   CRC32                 4 bytes
  93.  *   Size                  4 bytes
  94.  *
  95.  * Then follows the file data for each file, in the same order as the
  96.  * file headers.
  97.  */
  98.  
  99. #include <libraries/xadmaster.h>
  100. #include <proto/xadmaster.h>
  101. #include <string.h>
  102.  
  103. #include "SDI_compiler.h"
  104. #include "ConvertE.c"
  105.  
  106. #ifndef XADMASTERFILE
  107. #define Wrap_Client        FirstClient
  108. #define NEXTCLIENT        0
  109. const UBYTE version[] = "$VER: Wrapster 1.3 (17.08.2002)";
  110. #endif
  111. #define WRAP_VERSION        1
  112. #define WRAP_REVISION        3
  113.  
  114. #define XADBASE  REG(a6, struct xadMasterBase *xadMasterBase)
  115.  
  116. #define head_magic      (0x00)
  117. #define head_reserved   (0x04)
  118. #define head_signature  (0x0a)
  119. #define head_version    (0x14)
  120. #define head_filecount  (0x1c)
  121. #define head_SIZEOF     (0x20)
  122.  
  123. #define file_name       (0x000)
  124. #define file_reserved   (0x100)
  125. #define file_crc32      (0x120)
  126. #define file_size       (0x124)
  127. #define file_SIZEOF     (0x128)
  128.  
  129. ASM(BOOL) Wrap_RecogData(REG(d0, ULONG size), REG(a0, STRPTR d), XADBASE) {
  130.   return (BOOL) (d[0]==0xFF && d[1]==0xFB && d[2]==0x18 && d[3]==0x0C
  131.                  && (memcmp(&d[10], "wrapster\0", 10) == 0)) ? 1 : 0;
  132. }
  133.  
  134. ASM(BOOL) Wrap3_RecogData(REG(d0, ULONG size), REG(a0, STRPTR d), XADBASE) {
  135.   return (BOOL) (d[0]==0xFF && d[1]==0xFB && d[2]==0x90 && d[3]==0x04
  136.                  && (memcmp(&d[10], "wwapster\0", 10) == 0)) ? 1 : 0;
  137. }
  138.  
  139. ASM(LONG) Wrap_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  140.   UBYTE buf[file_SIZEOF], is_v3;
  141.   struct xadSkipInfo *slink = NULL,  *si;
  142.   struct xadFileInfo *fi;
  143.   ULONG numfiles, offset, skipto;
  144.   LONG err = XADERR_OK;
  145.  
  146.   struct TagItem nametags[] = {
  147.     { XAD_CHARACTERSET, CHARSET_WINDOWS },
  148.     { XAD_STRINGSIZE, 256 },
  149.     { XAD_CSTRING, 0 },
  150.     { TAG_DONE, 0 }
  151.   };
  152.  
  153.   struct TagItem datetags[] = {
  154.     { XAD_DATECURRENTTIME, 1 },
  155.     { XAD_GETDATEXADDATE,  0 },
  156.     { TAG_DONE, 0 }
  157.   };
  158.  
  159.   struct TagItem tags[] = {
  160.     { XAD_USESKIPINFO, 1 },
  161.     { TAG_DONE, 0 }
  162.   };
  163.  
  164.   /* read the file header */
  165.   if ((err = xadHookAccess(XADAC_READ, head_SIZEOF, buf, ai))) return err;
  166.  
  167.   /* is this a wrapster v3 file? */
  168.   is_v3 = (buf[2] == 0x90);
  169.  
  170.   /* skip all the mp3 frame headers */
  171.   if (is_v3) {
  172.     for (numfiles = ai->xai_InSize / 417; numfiles--; offset += 417) {
  173.       if (!(si = (struct xadSkipInfo *) xadAllocObjectA(XADOBJ_SKIPINFO,0)))
  174.         return XADERR_NOMEMORY;
  175.       si->xsi_Position = offset;
  176.       si->xsi_SkipSize = 4;
  177.       if (slink) slink->xsi_Next = si; else ai->xai_SkipInfo = si;
  178.       slink = si;
  179.     }
  180.   }
  181.  
  182.   /* check the version - is it "1.0", "2.0" or "3.0" ? */
  183.   if (buf[head_version] < '1' || buf[head_version] > '3') {
  184.     return XADERR_DATAFORMAT;
  185.   }
  186.  
  187.   /* get the number of files in this archive */
  188.   numfiles = EndGetI32(&buf[head_filecount]);
  189.  
  190.   if (is_v3) {
  191.     /* offset of the file data, NOT counting the mp3 headers */
  192.     offset = (head_SIZEOF-4) + (file_SIZEOF * numfiles);
  193.   }
  194.  
  195.   while (numfiles-- && ((ai->xai_InPos+file_SIZEOF) < ai->xai_InSize)) {
  196.     /* read the file header */
  197.     if ((err = xadHookTagAccessA(XADAC_READ, file_SIZEOF, buf, ai, tags))) {
  198.       break;
  199.     }
  200.  
  201.     /* allocate a file entry */
  202.     if (!(fi = (struct xadFileInfo *) xadAllocObjectA(XADOBJ_FILEINFO,NULL))) {
  203.       err = XADERR_NOMEMORY;
  204.       break;
  205.     }
  206.  
  207.     fi->xfi_Size  = fi->xfi_CrunchSize = EndGetI32(&buf[file_size]);
  208.     fi->xfi_Flags = XADFIF_SEEKDATAPOS | XADFIF_EXTRACTONBUILD;
  209.     if (is_v3) {
  210.       fi->xfi_DataPos = offset + (((offset/413)+1)*4);
  211.       offset += fi->xfi_Size;
  212.     }
  213.     else {
  214.       fi->xfi_DataPos = ai->xai_InPos;
  215.     }
  216.  
  217.     /* copy filename (and convert if necessary) */
  218.     nametags[2].ti_Data = (ULONG) &buf[file_name];
  219.     if (!(fi->xfi_FileName = xadConvertNameA(CHARSET_HOST, nametags))) {
  220.       err = XADERR_NOMEMORY;
  221.       break;
  222.     }
  223.  
  224.     /* fill in today's date */
  225.     datetags[1].ti_Data = (ULONG) &fi->xfi_Date;
  226.     xadConvertDatesA(datetags);
  227.  
  228.     /* add file entry. The xadAddFileEntry() automatic seeking tag
  229.      * XAD_SETINPOS cannot be used, because it does not support the
  230.      * XAD_USESKIPINFO tag (current as of XAD V12)
  231.      */
  232.     skipto = ai->xai_InPos + ((is_v3) ? 0 : fi->xfi_Size);
  233.     if ((err = xadAddFileEntryA(fi, ai, NULL))) break;
  234.     if (ai->xai_InPos != skipto) {
  235.       if ((err = xadHookTagAccessA(XADAC_INPUTSEEK, skipto - ai->xai_InPos,
  236.                                    NULL, ai, tags))) break;
  237.     }
  238.   }
  239.  
  240.   if (err) {
  241.     if (!ai->xai_FileInfo) return err;
  242.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  243.     ai->xai_LastError = err;
  244.   }
  245.   return XADERR_OK;
  246. }
  247.  
  248. ASM(LONG) Wrap_UnArchive(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  249.   struct TagItem tags[] = {
  250.     { XAD_USESKIPINFO, 1 },
  251.     { TAG_DONE, 0 }
  252.   };
  253.   return xadHookTagAccessA(XADAC_COPY,ai->xai_CurFile->xfi_Size,NULL,ai,tags);
  254. }
  255.  
  256. const struct xadClient Wrap3_Client = {
  257.   NEXTCLIENT, XADCLIENT_VERSION, 12,
  258.   WRAP_VERSION, WRAP_REVISION,
  259.   32, XADCF_FILEARCHIVER | XADCF_FREEFILEINFO |
  260.       XADCF_FREEXADSTRINGS | XADCF_FREESKIPINFO,
  261.   0, "Wrapster 3",
  262.  
  263.   /* client functions */
  264.   (BOOL (*)()) Wrap3_RecogData,
  265.   (LONG (*)()) Wrap_GetInfo,
  266.   (LONG (*)()) Wrap_UnArchive,
  267.   (void (*)()) NULL
  268. };
  269.  
  270. const struct xadClient Wrap_Client = {
  271.   (struct xadClient *) &Wrap3_Client, XADCLIENT_VERSION, 12,
  272.   WRAP_VERSION, WRAP_REVISION,
  273.   32, XADCF_FILEARCHIVER | XADCF_FREEFILEINFO | XADCF_FREEXADSTRINGS,
  274.   0, "Wrapster",
  275.  
  276.   /* client functions */
  277.   (BOOL (*)()) Wrap_RecogData,
  278.   (LONG (*)()) Wrap_GetInfo,
  279.   (LONG (*)()) Wrap_UnArchive,
  280.   NULL
  281. };
  282.